package com.cssw.fyzb.core.mongo;

import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Feng Chen
 */
public class MongoClient extends com.mongodb.MongoClient {

    private MongoDatabase database;

    private com.mongodb.MongoClient delegate;


    // 单机版

    public MongoClient(String host, int port, String dbname) {
        this(host, port, dbname, new MongoOptions());
    }

    public MongoClient(String host, int port, String dbname, MongoOptions options) {
        delegate = new com.mongodb.MongoClient(
                new ServerAddress(host, port),
                MongoClientOptions.builder()
                        .maxWaitTime(options.getMaxWaitTime())
                        .connectTimeout(options.getCoTimeout())
                        .socketTimeout(options.getSoTimeout())
                        .connectionsPerHost(options.getCoPerHost())
                        .threadsAllowedToBlockForConnectionMultiplier(options.getCoMultiplier())
                        .build()
        );
        database = delegate.getDatabase(dbname);
    }

    public MongoClient(String host, int port, String dbname, String user, String pwd) {
        this(host, port, dbname, user, pwd, new MongoOptions());
    }

    public MongoClient(String host, int port, String dbname, String user, String pwd, MongoOptions options) {
        delegate = new com.mongodb.MongoClient(
                new ServerAddress(host, port),
                MongoCredential.createCredential(
                        user,
                        dbname,
                        pwd.toCharArray()
                ),
                MongoClientOptions.builder()
                        .maxWaitTime(options.getMaxWaitTime())
                        .connectTimeout(options.getCoTimeout())
                        .socketTimeout(options.getSoTimeout())
                        .connectionsPerHost(options.getCoPerHost())
                        .threadsAllowedToBlockForConnectionMultiplier(options.getCoMultiplier())
                        .build()

        );
        database = delegate.getDatabase(dbname);
    }


    // 集群版

    public MongoClient(String seeds, String dbname) {
        this(seeds, dbname, new MongoOptions());
    }

    public MongoClient(String seeds, String dbname, MongoOptions options) {
        delegate = new com.mongodb.MongoClient(
                __seeds(seeds),
                MongoClientOptions.builder()
                        .maxWaitTime(options.getMaxWaitTime())
                        .connectTimeout(options.getCoTimeout())
                        .socketTimeout(options.getSoTimeout())
                        .connectionsPerHost(options.getCoPerHost())
                        .threadsAllowedToBlockForConnectionMultiplier(options.getCoMultiplier())
                        .build()
        );
        database = delegate.getDatabase(dbname);
    }

    public MongoClient(String seeds, String dbname, String user, String pwd, MongoOptions options) {
        delegate = new com.mongodb.MongoClient(
                __seeds(seeds),
                MongoCredential.createCredential(
                        user,
                        dbname,
                        pwd.toCharArray()
                ),
                MongoClientOptions.builder()
                        .maxWaitTime(options.getMaxWaitTime())
                        .connectTimeout(options.getCoTimeout())
                        .socketTimeout(options.getSoTimeout())
                        .connectionsPerHost(options.getCoPerHost())
                        .threadsAllowedToBlockForConnectionMultiplier(options.getCoMultiplier())
                        .build()
        );
        database = delegate.getDatabase(dbname);
    }

    // 获取指定的集合
    public MongoCollection<Document> getCollection(String collectionName) {
        return this.database.getCollection(collectionName);
    }

    public <T> MongoCollection<T> getCollection(String collectionName, Class<T> documentClass) {
        return this.database.getCollection(collectionName, documentClass);
    }

    public void close() {
        super.close();
    }


    // SECTION : INNER HELPER

    private List<ServerAddress> __seeds(String seeds) {
        String[] addrs = seeds.split(";|,");
        List<ServerAddress> list = new ArrayList<>();
        for (String addr : addrs) {
            String[] host = addr.split(":");
            list.add(new ServerAddress(host[0], Integer.parseInt(host[1])));
        }
        return list;
    }

}
